from python.infoer.models import SPS
from django.http import HttpResponse
import socket
from urlparse import urlparse

PROTOCOL = "Shuttle"
VERSION = "0.1"

ERRCODE_RESERVED = 80
ERRCODE_PROGMA_ERR				= ERRCODE_RESERVED + 1
ERRCODE_HTTP_PROTOCL_DISMATCH	= ERRCODE_RESERVED + 2
ERRCODE_INVALID_PORT_FORM		= ERRCODE_RESERVED + 3
ERRCODE_PARAM_TYPE_ERR			= ERRCODE_RESERVED + 4
ERRCODE_PARAM_VALUE_ERR			= ERRCODE_RESERVED + 5
ERRCODE_PARAM_MISSING			= ERRCODE_RESERVED + 6
ERRCODE_NO_ERROR				= ERRCODE_RESERVED + 80
#ERRCODE_

def validate_ipv4_address(addr):
	try:
		tmp = socket.inet_pton(socket.AF_INET, addr)
	except:
		return False
	return True
	
def validate_ipv6_address(addr):
	try:
		tmp = socket.inet_pton(socket.AF_INET6, addr)
	except:
		return False
	return True
	
def validate_ip_address(addr):
	return (validate_ipv4_address(addr) + validate_ipv6_address(addr))

def register_sps_handler(request):
	if request.method == 'POST':
		type = request.POST.get('sps_type', '')
		try:
			type = int(type)
		except:
			return (ERRCODE_PARAM_TYPE_ERR, "sps_type should a valid integer")
		
		secretkey = request.POST.get('secretkey', '')
		if not secretkey or len(secretkey) == 0:
			return (ERRCODE_PARAM_MISSING, "secretkey parameter is missing")
			
		if type in [1,2]:
			port = request.POST.get('port', '')
			ip_address = request.POST.get('ip_address', '')
			if not port: return (ERRCODE_PARAM_MISSING, "port parameter is missing")
			if not ip_address: return (ERRCODE_PARAM_MISSING, "ip_address parameter is missing")
			try:
				port = int(port)
			except:
				return (ERRCODE_PARAM_TYPE_ERR, "port should a valid integer")
			
			if port not in range(1,65535):
				return (ERRCODE_PARAM_VALUE_ERR, "port should range between 1 and 65535")
			if not validate_ip_address(ip_address):				
				return (ERRCODE_PARAM_VALUE_ERR, "invalid ip address")
			
			sps = None
			try:
				sps = SPS.objects.filter(ip_address=ip_address, port=port, type=['TCP', 'UDP'][type-1]).get()
			except:
				pass
			
			if sps:
				sps.secretkey = secretkey
				sps.save()
				return (ERRCODE_NO_ERROR, "SPS running on %s:%i has been updated" % (ip_address, port))

			
			new_sps = SPS()
			new_sps.type = ['TCP', 'UDP'][type-1]
			new_sps.port = port
			new_sps.ip_address = ip_address
			new_sps.secretkey = secretkey
			new_sps.save()
			
			return (ERRCODE_NO_ERROR, "SPS running on %s:%i has been registered" % (ip_address, port))

		elif type in [3]:
			url = request.POST.get('url', '')
			if not url or not len(url):
				return (ERRCODE_PARAM_MISSING, "url parameter is missing")
			
			parsed_url = urlparse(url)
			if parsed_url.scheme.lower() not in ("http", "https"):
				return (ERRCODE_PARAM_VALUE_ERR, "invalid url scheme")
			
			sps = None
			try:
				sps = SPS.objects.filter(url=url, type=parsed_url.scheme.upper()).get()
			except:
				pass
			
			if sps:
				sps.secretkey = secretkey
				sps.save()
				return (ERRCODE_NO_ERROR, "SPS running on %s has been updated" % (url))
			
			new_sps = SPS()
			new_sps.type = parsed_url.scheme.upper()
			new_sps.url = url
			new_sps.secretkey = secretkey
			new_sps.save()
			
			return (ERRCODE_NO_ERROR, "SPS running on %s has been registered" % (url))
			
		else:
			return (ERRCODE_PARAM_VALUE_ERR, "sps_type should range between 1 and 3")
	else:
		return (ERRCODE_HTTP_PROTOCL_DISMATCH, "HTTP protocol has to be POST")
	return (ERRCODE_PROGMA_ERR, "")

def register_sps(request):
	protocol = PROTOCOL
	version = VERSION
	
	errcode, message = register_sps_handler(request)
	
	output = "%i %s/%s %s" % (errcode, protocol, version, '"' + message + '"')
	return HttpResponse(output)
